<template>
  <!-- 7月13号------------------------7月13号------------------------ -->
  <div class="departments-container">
    <!-- Card 卡片,作用就是,一个带阴影的盒子 -->
    <el-card>
      <!-- Tabs 标签页, `tabs`组件的作用是标签切换 -->
      <el-tabs v-model="activeName">
        <el-tab-pane label="组织结构" name="first">
          <!-- layout 布局 ,顶部顶部布局,通过基础的 24 分栏，迅速简便地创建布局。 -->
          <!--  属性赋值为 'flex'，可以启用 flex 布局 -->
          <!-- 并可通过 justify 属性来指定 start, center, end, space-between, space-around 其中的值来定义子元素的排版方式 -->
          <el-row type="flex" justify="space-between">
            <el-col :span="6">
              <div class="lin"><a href="">深圳市凌凌漆科技股份有限公司</a></div>
            </el-col>
            <el-col :span="4" class="right-clo">
              <span class="leader">负责人:</span>
              <!-- 为啥使用div后 负责人这几个字会在下拉菜单的头上? -->
              <!-- <div class="leader">负责人</div> -->
              <!-- Dropdown-下拉菜单 -->
              <el-dropdown type="primary">
                <span class="el-dropdown-link">
                  下拉菜单
                  <!-- 一个下拉箭头的图标 -->
                  <i class="el-icon-arrow-down el-icon--right"></i>
                </span>
                <!-- 点击后展开的部分 -->
                <el-dropdown-menu slot="dropdown">
                  <el-dropdown-item>
                    <!-- @click="showDialog('')传一个空,意思就是当前添加的这个节点,pid是空 -->
                    <el-button @click="showDialog('')" type="text"
                      >添加子部门</el-button
                    >
                  </el-dropdown-item>
                  <el-dropdown-item>
                    <el-button type="text">凌凌漆</el-button>
                  </el-dropdown-item>
                </el-dropdown-menu>
              </el-dropdown>
            </el-col>
          </el-row>
          <!-- Element - Divider分割线, -->
          <el-divider />
          <!-- 底部底部底部底部底部底部------------------------------------------------------------------------------- -->
          <!-- Element-Tree 树形控件 -->
          <el-tree :data="departs" v-loading="loading">
            <!-- 7月13号---------------------7月13号-------------------------------------- -->
            <!-- 和顶部一样的结构 -->
            <!-- 在Tree树形控件里面,有自定义节点内容,然后里面有slot-scope="{ node, data }" -->
            <!-- 通过node也可以点出leader,但是data也可以,所以就用data一个就行 -->
            <!-- style="width:100%"是因为之前盒子默认没有铺满,所以才加的 -->
            <!-- el-tree里面传递了el-row这个结构,用的是插槽的计算,目前这里是传递了一推的结构,相当于是 -->
            <!-- 他默认的渲染方式已经满足不到我的开发需求了,所以怎么渲染数据是开发人员说了算,所以就不需要 -->
            <!-- 给他设置官网自带的:props="defaultProps这个属性了,因为需要开发人员解决需要什么数据了 -->
            <template #default="{ data }">
              <!-- 项目之前的slot-scope="{ data }"废弃的语法(下载el-row标签里面),所以改成了最新的语法,但是需要包裹在template标签使用 -->
              <!-- vue官网定义的:::插槽名 (可选，默认值是 default) -->
              <el-row type="flex" justify="space-between" style="width:100%">
                <el-col :span="6">
                  <!-- data.name,下面data中departs里面的数据 -->
                  <div>{{ data.name }}</div>
                </el-col>
                <el-col :span="4" class="right-clo">
                  <!-- data.manager就是取值,下面data中departs里面的数据 -->
                  <span class="leader">{{ data.manager }}:</span>
                  <!-- Dropdown 下拉菜单 -->
                  <el-dropdown>
                    <span class="el-dropdown-link">
                      操作
                      <!-- 一个下拉箭头的图标 -->
                      <i class="el-icon-arrow-down el-icon--right"></i>
                    </span>
                    <!-- 点击后展开的部分 -->
                    <el-dropdown-menu slot="dropdown">
                      <el-dropdown-item>
                        <!-- 新增子节点,把这一行的id,传递到新增子节点的方法这中去,(data就是这一样的数据,里面有id,然后子节点的pid,等于顶级节点的id,那说明新增的是子节点,通话这个去做判断) -->
                        <el-button @click="showDialog(data.id)" type="text"
                          >添加子部门</el-button
                        >
                      </el-dropdown-item>
                      <el-dropdown-item>
                        <!--  @click="enterEdit"进入编辑事件 -->
                        <el-button @click="enterEdit(data.id)" type="text"
                          >查看部门</el-button
                        >
                      </el-dropdown-item>
                      <el-dropdown-item>
                        <el-button
                          @click="removeDepartment(data.id)"
                          type="text"
                          >删除部门</el-button
                        >
                      </el-dropdown-item>
                    </el-dropdown-menu>
                  </el-dropdown>
                </el-col>
              </el-row>
            </template>
          </el-tree>
        </el-tab-pane>
      </el-tabs>
      <!-- 下拉菜单 -->
      <!-- 文字按钮 -->
    </el-card>
    <!-- 弹框弹框 -->
    <!-- Element-Dialog 对话框 -->
    <!-- Dialog 组件的内容可以是任意的，甚至可以是表格或表单，下面是应用了 Element Table 和 Form 组件的两个样例。 -->
    <!-- Emelent-Dialog 对话框里面有一个禁用图标的方法 :show-close="false",是否显示关闭按钮 -->
    <!-- 7月16号修改, @closed="closedHandler",Dialog 关闭动画结束时的回调 -->
    <el-dialog
      :title="title"
      :visible.sync="dialogFormVisible"
      :show-close="false"
      @closed="closedHandler"
    >
      <el-form ref="depForm" :rules="rules" :model="form">
        <el-form-item
          prop="name"
          label="部门名称"
          :label-width="formLabelWidth"
        >
          <el-input v-model="form.name" autocomplete="off" />
        </el-form-item>
        <el-form-item
          prop="code"
          label="部门编码"
          :label-width="formLabelWidth"
        >
          <el-input v-model="form.code" autocomplete="off" />
        </el-form-item>
        <el-form-item
          prop="manager"
          label="部门负责人"
          :label-width="formLabelWidth"
        >
          <!-- focus当 input 获得焦点时触发,Emelent官网定义的方法, @focus="getManagers" -->
          <el-select
            @focus="getManagers"
            v-model="form.manager"
            placeholder="请选择"
          >
            <el-option
              v-for="item in managerList"
              :key="item.id"
              :value="item.username"
            />
          </el-select>
        </el-form-item>
        <el-form-item
          prop="introduce"
          label="部门介绍"
          :label-width="formLabelWidth"
        >
          <el-input v-model="form.introduce" autocomplete="off" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="clickcancel">取 消</el-button>
        <el-button type="primary" @click="submitForm('depForm')"
          >确定</el-button
        >
      </div>
    </el-dialog>
  </div>
</template>

<script>
// 7月14号------------------------7月14号------------------------
// 获取员工的简单列表(在弹框里面选中部门负责人的时候调用接口)
import { getEmployeeSimple } from '../../api/employees.js'
// 7月13号------------------------7月13号------------------------
// 导入查询企业的部门列表的接口,在api/departments.js
// 7月13号导入getDepartments(查询企业的部门列表的接口)
// 7月14号导入 addDepartments(新增组织架构接口)
// 7月14号导入 getDepartmentById(根据id获取部门信息的接口(查看部门信息),进行编辑用)
// 7月14号导入 editDepartment,修改部门信息在
// 7月15号导入 delDepartmentById,删除部门信息
import {
  getDepartments,
  addDepartments,
  getDepartmentById,
  editDepartment,
  delDepartmentById
} from '../../api/departments.js'
export default {
  name: 'Departments',
  data () {
    return {
      loading: false,
      // 7月14号------------------------7月14号------------------------
      // 是否显示弹框
      dialogFormVisible: false,
      // 表单数据(要和服务器接口地址,需要的参数一致)
      form: {
        code: '',
        introduce: '',
        manager: '',
        name: '',
        pid: ''
      },
      formLabelWidth: '120px', //左侧的宽度
      managerList: [], // 存储,获取员工的简单列表的数据
      // 上面是7月14号的,下面也是7月14号的
      // ----------------------------------------------------------------------------
      // 校验form表单规则
      // 111,在el-from绑定一:rules="rules"
      // 222,rules效验的规则定义在data中
      // 333,然后不同的字段需要去运用对应的规则,这个规则的对应关系是通过el-from标签里面的</el-form-item>里面的prop="introduce" prop="manager" prop="name"进行对应的
      // required必填项,min和max最小和最大,message提示信息,trigger触发的方式('blur'是失去焦点),change是改变
      // 校验代码在,Element-Form 表单里面就有
      rules: {
        // 部门名称
        name: [
          { required: true, message: '部门名称不能为空', trigger: 'blur' },
          { min: 1, max: 50, message: '长度为1-15个字', trigger: 'blur' },
          // 重点(Element-自定义校验规则,官网方法)
          // 1,在rules对应的字段数组上去效验(一般是校验一些不能重复的name,或者id)
          // 2,value是校验的字段(当前校验字段的值),callback是回调函数,有两个定义 第一个callback()就是成功 第二个callback(new Error('错误提示的信息'))失败
          // 3,同过接口获取数据,然后进行校验(获取查询企业的部门列表的数据,然后进行校验)
          // 111,完整写法
          // {
          //   async validator (rule, value, callback) {
          //     // 同过接口获取数据,然后进行校验(因为是一个ajax的请求,所以用async)
          //     // 获取查询企业的部门列表的数据,然后进行校验
          //     const res = await getDepartments()
          //     // console.log('res', res) // 打印看看能不能拿到数据
          //     // filter过滤(通过filter这个方法找到符合条件的元素)
          //     const filterRes = res.depts.filter(v => {
          //       if (value === v.name) {
          //         return true
          //       } else {
          //         return false
          //       }
          //     })
          //     if (filterRes.length === 0) {
          //       // 判断filterRes如果长度等于0，说明，没有重复
          //       callback()
          //     } else {
          //       // 否则就是，有重复的
          //       callback(new Error('部门名称-重复.请重新输入!'))
          //     }
          //   },
          //   trigger: 'blur'
          // }
          // 222,简化写法,使用filter
          // {
          //   async validator (rule, value, callback) {
          //     const res = await getDepartments()
          //     res.depts.filter(v => value === v.name).length === 0
          //       ? callback()
          //       : callback(new Error('部门名称-重复.请重新输入!'))
          //   }
          // }
          // 333,简化写法,使用 some(some判断数组中是否存在某个元素),还有every
          // 只要有任何一个name和输入的值相同,那就是true
          // {
          //   async validator (rule, value, callback) {
          //     const res = await getDepartments()
          //     res.depts.filter(v => value === v.name)
          //       ? callback()
          //       : callback(new Error('部门名称-重复.请重新输入!'))
          //   }
          // },
          // 7月16号------------------------7月16号------------------------
          // bug修改03,编辑状态的时候,可以重名(也可以和id相同) 但是名字和id不同就不允许
          // 加了判断的写法
          {
            validator: async (rule, value, callback) => {
              // 这里的后面不能加.length === 0,如果加了随便输入一个字,就提示error
              const res = await getDepartments()
              // 111,this的指向是这个函数最终调用时候的指向,(这个需要用箭头函数,用了箭头函数后,你创建的时候,this就是谁,他就是谁)
              // 所以,目前这个打印不来是因为没有用箭头函数去绑定this,导致调用时候的this确实不到,所以改箭头函数
              // 箭头函数的特点是,当他在创建的时候,this会把当前作用域的this给绑定上,并且永不改变(data中的this就是vue实例对象)
              // 222.判断,当this.form.id,说明是有值得,那就是编辑
              // 如果输入的vlaue的值,在服务器返回的数据中存在,新增时就直接报错
              // 如果输入的vlaue的值,在服务器返回的数据中存在,同时,和当前编辑的id,不相等
              // 就说明是改了一个其他的名字,(那编辑的时候就报错)
              const checkRes = res.depts.some(v => {
                if (this.form.id) {
                  // 判断vlaue相等, id不相等
                  // 111,编辑判断输入的vlaue值可以相等,但是id不能相等(所以输入同名不会触发校验)
                  if (value === v.name && this.form.id !== v.id) {
                    return true
                  }
                } else {
                  // 新增,编辑判断输入的vlaue值可以相等
                  if (value === v.name) {
                    // 存在
                    return true
                  }
                }
              })
              // console.log('checkRes', checkRes)
              // 上面新增判断的是value === v.name(输入框的信息等于遍历出来的name是)
              // 返回的是true,然后提示一个错误,(相等才提示错误,不等就不提示呗)
              checkRes === true
                ? callback(new Error('部门名称-重复.请重新输入!'))
                : callback()
            }
          }
          // 7月16号----------重点--------------7月16号------------------------
        ],
        // 部门编码,重点看
        code: [
          { required: true, message: '部门编码不能为空', trigger: 'blur' },
          { min: 1, max: 15, message: '长度为1-15个字', trigger: 'blur' },
          // {
          //   async validator (rule, value, callback) {
          //     // 同过接口获取数据,然后进行校验(因为是一个ajax的请求,所以用async)
          //     // 获取查询企业的部门列表的数据,然后进行校验
          //     const res = await getDepartments()
          //     // console.log('res', res) // 打印看看能不能拿到数据
          //     // filter过滤(通过filter这个方法找到符合条件的元素)
          //     const filterRes = res.depts.filter(v => {
          //       if (value === v.code) {
          //         return true
          //       } else {
          //         return false
          //       }
          //     })
          //     if (filterRes.length === 0) {
          //       // 判断filterRes如果长度等于0，说明，没有重复
          //       callback()
          //     } else {
          //       // 否则就是，有重复的
          //       callback(new Error('部门编码-重复.请重新输入!'))
          //     }
          //   },
          //   trigger: 'blur'
          // }
          // 上面是没加判断的写法
          // 7月16号----------重点--------------7月16号------------------------
          // bug修改03,编辑状态的时候,可以重名(也可以和id相同) 但是名字和id不同就不允许
          // 加了判断的写法
          {
            validator: async (rule, value, callback) => {
              // 这里的后面不能加.length === 0,如果加了随便输入一个字,就提示error
              const res = await getDepartments()
              // 111,this的指向是这个函数最终调用时候的指向,(这个需要用箭头函数,用了箭头函数后,你创建的时候,this就是谁,他就是谁)
              // 所以,目前这个打印不来是因为没有用箭头函数去绑定this,导致调用时候的this确实不到,所以改箭头函数
              // 箭头函数的特点是,当他在创建的时候,this会把当前作用域的this给绑定上,并且永不改变(data中的this就是vue实例对象)
              // 222.判断,当this.form.id,说明是有值得,那就是编辑
              // 如果输入的vlaue的值,在服务器返回的数据中存在,新增时就直接报错
              // 如果输入的vlaue的值,在服务器返回的数据中存在,同时,和当前编辑的id,不相等
              // 就说明是改了一个其他的名字,(那编辑的时候就报错)
              const checkRes = res.depts.some(v => {
                if (this.form.id) {
                  // 判断vlaue相等, id不相等
                  // 111,编辑判断输入的vlaue值可以相等,但是id不能相等(所以输入同名不会触发校验)
                  if (value === v.code && this.form.id !== v.id) {
                    return true
                  }
                } else {
                  // 新增,编辑判断输入的vlaue值可以相等
                  if (value === v.code) {
                    // 存在
                    return true
                  }
                }
              })
              // console.log('checkRes', checkRes)
              checkRes === true
                ? callback(new Error('部门编码-重复.请重新输入!'))
                : callback()
            }
          }
        ],
        // blur失去焦点,change是改变
        // 部门负责人的长度校验可以不需要,因为是选择框的,然后选择框用change合适写,trigger: 'change'(用blur也可以)
        manager: [
          { required: true, message: '部门负责人不能为空', trigger: 'change' },
          { min: 1, max: 15, message: '长度为1-10个字', trigger: 'change' }
        ],
        // 部门介绍
        introduce: [
          { required: true, message: '部门介绍不能为空', trigger: 'blur' },
          { min: 1, max: 188, message: '长度为1-188个字', trigger: 'blur' }
        ]
      },
      // -------------------------------------------------------------
      // 管理员列表
      activeName: 'first',
      // 存储树状结构的数据
      departs: [
        {
          name: '总裁办',
          manager: '曹操',
          children: [{ name: '董事会', manager: '曹丕' }]
        },
        { name: '行政部', manager: '刘备' },
        { name: '人事部', manager: '孙权' }
      ]
    }
  },
  // 7月13号------------------------7月13号------------------------
  // 在created,生命周期钩子函数里面调用接口
  async created () {
    // 默认调用数据的逻辑(查询企业的部门列表的接口)
    this.getData()
  },
  methods: {
    // 7月14号----------------------7月14号----------------------
    // 获取员工的简单列表(focus当 input 获得焦点时触发,官网定义的, @focus="getManagers")
    async getManagers () {
      const res = await getEmployeeSimple()
      // console.log('res', res)
      this.managerList = res
    },
    // ----------------------------------------------------
    // 这里是把之前created逻辑定义在了getData这个方法里面
    async getData () {
      // 加载loading
      this.loading = true
      // 7月14号-------重点重点---------------7月14号----------------------
      // 这是优化的写法  (查询企业的部门列表的接口)+ 调优数组转树逻辑(可以无限加子节点三级,四级)
      const res = await getDepartments()
      // 递归 必须有个函数 这个函数的作用是,基于给定的 pid 返回满足条件的数组
      // filter是获取到筛选后的数组
      // list是传进去的数组,是需要从哪里进行帅选的数组,pid最开始循环,跟找子节点的循环,pid是不一样的,所以需要传递进来,因为你也不清楚需要帅选什么样的
      function formtData (list, pid) {
        // 这个需要把帅选后的数组返回出去,返回出去后,只要调用formtData这个方法,那就可以拿到一个数组
        return list.filter(v => {
          // 判断v.pid===传递进来的pid,然后传递进来的这个pid不能固定,(因为需要用这个方法不仅需要帅选出最外层,还需要帅选里面的二层,三层)
          if (v.pid === pid) {
            // 后续所有的节点,都应该以children的方式存在于上一个节点的下面
            // 这里的list,依旧是用最大的那个数组来帅选,但是这一次的帅选条件,就不是最初的pid了,而是需要找当前元素的子节点
            // 那么当前元素的子节点,相当于是你遍历的新的元素,然后里面的v.id(这是需要帅选的条件),后续找出来的所有结果,(都是当前这个元素的id,才能是谁的子节点)
            // 筛选子节点的条件是 循环数组的 每一项的 pid 和 当前这一项的 id 相等(所以pid===最大数据的v.id,那就说明他是顶级节点,依次无限循环也是如此)
            // 为什么加了下面这句代码就可以新建二级,三级子节点了呢?(写在下面了)
            // 这里就是添加了一个条件, 满足这个条件后才会调用这个方法
            v.children = formtData(list, v.id)
            // 如果相等就返回return (说明需要这个元素)
            return true
          } else {
            // 如果不等就是false (不需要这个元素)
            return false
          }
        })
      }
      // 只要调用formtData这个方法,那就可以拿到一个数组(因为上面返回出去了)
      // 第一次调用执行这个代码的时候,需要找的是最外层的,所以pid给的是空,所以第一次循环就找到最外层的数据
      // 那第二层,就加了 v.children = formtData(list, v.id)里面多了一个children的属性,(那我怎么知道谁是谁的子节点呢)
      // 只要能满足当前遍历的这个数组的pid和当前这一项的id相等,那就说明是当前这一项的子节点了(重点就是每次遍历的时候,都把帅选的条件调整了,如果能找到子节点,就会继续往里面去找,如果没有子节点了,这个循环就结束了)

      // 分析,最开始的list是通过服务器返回的数据拿到的(res.depts),它有是一个对象,既然是对象,遍历出现的v就是对应res.depts对象里面的每一个属性
      // 对象点出来一个不存在的属性,是不会报错的,是等undefined,同时因为res.depts是一个对象,然后v.children就相当于是在res.depts这个对象里面
      // 额外的添加了一个属性,但是但是,在调用formtData(list, v.id)他不一定有后代,如果有后代那么res.depts里面的childre:Array[0]就不可能是0
      // childre:Array[0]元素的个数是几个,是取决于formtData(list, v.id)执行的结果,所以如果循环完成后,发现里面有后代,就会再次递归调用formtData(list, v.id)这个方法
      // 但是如果循环后找不到后代了,那就进不去formtData(list, v.id)这个方法,(就相当于是无穷尽的找后代,找不到就停止,)
      // 第一次筛选 pid 是 ''
      const treeRes = formtData(res.depts, '')
      // 直接赋值即可
      this.departs = treeRes
      // 关闭loading
      setTimeout(() => {
        this.loading = false
      }, 500)
      // -------------------------------------------------------------------------------------
      // 7月13号----------------------7月13号------------------------------------------
      // 111,这是冗余的写法-----(这里只能加到二级的子节点, 三级的加了就不能显示)
      // const res = await getDepartments()
      // // 打印出来的数据,查看后得出(财务部id: "604e2251b205b95968e1312c" ,在财务部里面的,财务核算部(就是parent id的意思,就是父节点的id) pid: "604e2251b205b95968e1312c")
      // // 也就是说,财务部里面的其他部门的pid都是财务部的id,
      // // pid为空的是顶级节点,就是树形结构的最外层
      // // children就是子节点,需要如何去确实这个东西是子节点??pid和某个数据的id相同,就说明这条数据id对应数据的子节点
      // console.log('res', res)
      // // 111,先帅选出pid:''为空的,这就是最外层的节点(顶级节点)
      // // filter过滤
      // const rootTree = res.depts.filter(v => {
      //   if (v.pid === '') {
      //     return true
      //   } else {
      //     return false
      //   }
      // })
      // // 打印出来就是全部的顶级节点,(比如,总裁办,行政部,人事部这些)
      // // console.log('rootTree', rootTree)
      // // 222,筛选出后代节点, 就是children子节点
      // // 要用找出来的(rootTreed顶级节点)去遍历他里面的子节点,forEach就是遍历所以
      // // 先遍历,然后再,filter过滤
      // rootTree.forEach(rV => {
      //   const children = res.depts.filter(v => {
      //     // rV.id就是rootTree里面的顶级节点id,,,v.pid就是children子节点里面的pid
      //     // 所以过滤的v.pid和遍历出来当前节点的rv.id相同,那就说明这个v.pid这个节点,是当前rv.id的子节点
      //     if (v.pid === rV.id) {
      //       return true
      //     } else {
      //       return false
      //     }
      //   })
      //   // 打印出来是全部的children子节点(注意,并不是全部都有子节点哦,有的是没有)
      //   // console.log('children', children)
      //   rV.children = children
      // })
      // // 333,替换数据
      // // 因为在data中默认绑定了一个数据departs,和服务器返回的数据字段是一样的,所以直接替换就行
      // this.departs = rootTree
    },
    // 7月14号------------------------7月14号------------------------
    // 点击添加下拉菜单中的 添加子部门(顶级节点,和子节点,都是这个事件,只是传递的参数不一样来决定新增的内容)
    // 顶级节点的点击事件传递的是@click="showDialog('')",pid为空,空就代表新增的是顶级节点,
    // 子节点的点击事件@click="showDialog(data.id)"传递了当前这行的id,然后子节点的pid,等于顶级节点的id,那说明新增的是子节点,通话这个去做判断)
    showDialog (pid) {
      // (显示form框的方法)
      this.form.pid = pid // 讲点击事件带的pid参数,赋值到form表单中(pid为空,说明是新增顶级节点,pid有值说明是新增耳机节点)
      // console.log('pid', pid)
      this.dialogFormVisible = true
    },
    // 7月14号------------------------7月14号------------------------
    // 点击确定,提交表单,Element提交事件(官网的事件)
    // 111,需要在el-from标签里面添加一个字段ref="depForm"
    // 222,然后声明点击事件submitForm(如果点击事件带参数就需要这样写 @click="submitForm('depForm')",注意参数必须是字符串格式)
    //     如果点击事件不带参数,那么 this.$refs[depForm]的数组就需要删除,改成 this.$refs.depForm
    submitForm (depForm) {
      // ref="depForm"
      // 通过refs,获取到elment-form组件,并调用校验
      this.$refs[depForm].validate(async valid => {
        if (valid) {
          // 判断提交的时候是新增,还是,编辑
          if (this.form.id) {
            // 1,id存在就是编辑 (修改部门信息在的接口)
            const editRes = await editDepartment(this.form)
            // 2,编辑完成,提示编辑成功(Element官网的提示插件)
            this.$message.success('编辑成功')
          } else {
            // id不存就是新增
            // 1,校验通过,提交数据,(新增组织架构接口)
            const addRes = await addDepartments(this.form)
            // 2,表单校验完成后,提示新增成功(Element官网的提示插件)
            this.$message.success('新增成功')
          }
          // 3,关闭from框
          this.dialogFormVisible = false
          // 4,刷新数据(重新调用一次接口)
          this.getData()
          // 5,清空form表单数据,Emelent官网定义的清空语法(有可能清除不到),(新增成功数据后去清空)
          // 如果其他有一个方法清空不到,那就开启两个
          // this.$refs[depForm].resetFields()
          // 6,原生写法
          this.form = {}
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    // 点击form框里面的取消逻辑
    clickcancel () {
      // 清空form表单数据,Emelent官网定义的清空语法,(刷新完成数据后去清空)
      // this.$refs[depForm].resetFields()
      // 原生写法
      this.form = {}
      this.dialogFormVisible = false
    },
    // 7月16号------------------------7月16号-----------------------------------------------------------
    // 处理上面点击事件的存在的bug  (在Dialog标签里面的定义了closed这个方法)
    // bug修复01(目前这里存在的问题是,点击查看部门后进入编辑状态,然后不点击取消,而是点击页面其他的位置也会关闭弹框,然后再点击新增部门,此时form数据是不能清空的)
    // Emelent-里面的Dialog对话框里面有一个Events事件里面有一个,closed Dialog 关闭动画结束时的回调(就是弹框关闭时)
    closedHandler () {
      // 注意,,,用了这个closed方法后,点击取消事件的逻辑就可以写到里面来,但是取消事件需要写在行内
      // console.log('关闭了')
      // 注意注意,分析分析,在编辑的时候取消是需要清空form数据的,但是在新增的时候就不能清空
      // 判断有id就是编辑,新增数据是没有id的
      if (this.form.id) {
        this.form = {
          code: '',
          introduce: '',
          manager: '',
          name: '',
          pid: ''
        }
      } else {
      }
      // bug修复02 (取消后,会清空form的数据, 但是在点击新增的时候,就会触发表单的校验,部门负责人的, 现在就是处理这个bug)
      // 所以清空表单的校验,Emelent-Form表单里面的Form Methods里面的clearValidate方法(移除表单项的校验结果)
      // (重点111,注意了,如果没有写这句代码之前,也不触发效验提示,那么就说明是在data中的效验逻辑里面的trigger: 'blur',改成change就触发提示了)

      this.$nextTick(() => {
        console.log(this.$refs.depForm) // 打印能到depForm这个数据的方法?
        // 重点222,刚更改数据的时候,数据的改变,到数据渲染页面是异步的操作,所以form数据没有更新到页面上的时候,代码就执行了
        // 所以需要用$nextTic(vue提供的一个解决方案),就是数据更新完成,页面同步完成后,才执行的函数
        // 注意333,可以把这个案例和思路整理成面试题
        // 注意444,因为closedHandler()关闭动画结束时的回调这个方法,没有带depForm参数,
        // 所以这里就不能用 this.$refs[depForm].clearValidate(),而是需要把数组去掉
        this.$refs.depForm.clearValidate()
      })
      // 7月16号------------------------7月16号-----------------------------------------------------
    },
    // 7月14号------------------------7月14号------------------------
    // 点击form弹框里面的查看部门 进入编辑状态事件(调用,根据id获取部门信息的接口(查看部门信息))
    async enterEdit (id) {
      // console.log('id', id) // 查看是否能拿到id
      // 111，获取数据(注意注意必须是先获取数据,如果先弹框,那么在获取数据,部门名字的效验就会触发)
      const res = await getDepartmentById(id)
      // console.log('res', res) // 查看是否能获取到数据
      // 222，将获取到的数据赋值给form表单
      this.form = res
      // 333，弹出form表单
      this.dialogFormVisible = true
    },
    // 7月15号------------------------7月15号------------------------
    // 删除部门信息
    removeDepartment (id) {
      console.log('id', id) // 查看是否能获取到id
      // 111,Emelent-MessageBox 弹框
      this.$confirm('次操作将删除改部门, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async () => {
          // 222,删除部门信息的接口
          const delres = await delDepartmentById(id)
          // console.log('delres', delres)
          this.$message({
            type: 'success',
            message: '删除成功!'
          })
          // 333,删除完成后更新数据
          this.getData()
        })
        .catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          })
        })
    }
  },
  // 因为编辑和新增用的是同一个框,所以需要通过一些条件去判断是编辑还是新增
  // 计算属性
  // 编辑才需要id,新增不需要id,所以根据form里面是否有这个id,去判断显示(编辑部门,还是新增部门)
  computed: {
    title () {
      // 注意,这里需要返回出去,才能绑定到这里的方法
      return this.form.id ? '编辑部门' : '新增部门'
    }
  }
}
</script>
//
为什么这里不用scoped写样式,scoped就等于加了一个限制的范围,scoped作用就是防止全局同名CSS污染,
//
目前这里的样式已经是全部都包裹在.departments-container这个div里面了,相当于已经加了一个作用范围,所以就不需要用scoped
// 弊端,scoped如果添加了很多定义属性,那么会对新能造成一定的影响
<style lang="scss">
.departments-container {
  padding: 20px;
  .leader {
    display: inline-block;
    width: 60px;
    height: 20px;
    font-size: 16px;
    margin-right: 8px;
    color: #faf8f8;
    background-color: #069ef7;
    border-radius: 5px;
    text-align: center;
  }
  .el-tabs__content {
    padding: 20px 66px;
  }
  .el-divider {
    margin-top: 10px;
  }
  .right-clo {
    text-align: right;
  }
}
.el-tree-node__content {
  margin-top: 6px;
  border-bottom: 1px solid #ccc;
}
.lin > a {
  font-size: 18px;
  color: #069ef7;
}
</style>
